﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using OneWorks.Web.Common.Configuration;

namespace OneWorks.Web.Common
{
    /// <summary>
    /// Web文件上传简单处理
    /// </summary>
    public class FileUploadHandler
    {
        private readonly HttpPostedFileBase _baseFile;

        private readonly UploadFileConfigElement _configElement;

        private static readonly Dictionary<int, string> Errormessage = new Dictionary<int, string>
                                                                           {
                                                                               { 1000, "上传对象错误" },
                                                                               { 1001, "上传配置错误" },
                                                                               { 1002, "验证文件类型表达式格式不正确" },
                                                                               { 1003, "文件格式不正确" },
                                                                               { 1004, "设置上传文件名方法错误" }
                                                                           };

        #region constructor

        public FileUploadHandler(string key, HttpPostedFileBase baseFile)
        {
            UploadFileSection uploadFileSection = ConfigurationManager.GetSection("UploadFileConfig") as UploadFileSection;

            if (uploadFileSection == null) throw new ConfigurationErrorsException(Errormessage[1001]);

            _configElement = uploadFileSection.MultipleConfig[key];
            _baseFile = baseFile;

            if (_baseFile == null)
                throw new ArgumentNullException(Errormessage[1000]);

            VerifyConfig();
        }

        public FileUploadHandler(UploadFileConfigElement configElement, HttpPostedFileBase baseFile)
        {
            _configElement = configElement;
            _baseFile = baseFile;

            if (_baseFile == null)
                throw new ArgumentNullException(Errormessage[1000]);

            VerifyConfig();
        }

        #endregion

        #region private

        private void VerifyConfig()
        {
            if (_configElement == null)
                throw new ArgumentNullException(Errormessage[1001]);
            if (_configElement.Format.IndexOf('|') == -1)
                throw new ArgumentException(Errormessage[1002]);

        }

        /// <summary>
        /// 验证文件后缀
        /// </summary>
        /// <returns>true:验证通过,false:格式不正确</returns>
        private bool VerifySuffix()
        {
            string regExp = string.Format(@"^.*?\.({0})$", _configElement.Format);
            var suffix = Path.GetExtension(_baseFile.FileName);
            return !string.IsNullOrEmpty(suffix) && Regex.IsMatch(suffix, regExp);
        }

        /// <summary>
        /// 文件夹目录处理
        /// </summary>
        private string DirectoryProcess()
        {
            string path = HttpContext.Current.Request.MapPath(_configElement.VirtualPath);
            if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            return path;
        }

        #endregion

        #region public

        /// <summary>
        /// 虚拟目录
        /// </summary>
        public string VirtualPath
        {
            get
            {
                return _configElement.VirtualPath;
            }
        }

        /// <summary>
        /// 保存上传文件
        /// </summary>
        /// <returns></returns>
        public string Save()
        {
            return Save(HttpContext.Current);
        }

        /// <summary>
        /// 保存上传文件,设置上传文件名称,路径为HttpContext.MapPath
        /// </summary>
        /// <param name="httpContext">当前请求处理的上下文对象</param>
        /// <param name="getNameFunc">获取上传文件名称</param>    
        /// <returns></returns>
        public string Save(HttpContext httpContext, Func<string> getNameFunc = null)
        {
            if (!VerifySuffix()) throw new ArgumentException(Errormessage[1003]);
            string fileName = getNameFunc == null ? Guid.NewGuid().ToString() : getNameFunc();
            if (string.IsNullOrEmpty(fileName)) throw new ArgumentException(Errormessage[1004]);
            string path = DirectoryProcess();
            var suffix = Path.GetExtension(_baseFile.FileName);
            string fullFileName = path + fileName + suffix;
            _baseFile.SaveAs(fullFileName);
            return fullFileName;
        }

        #endregion
    }
}
